package jukebox.model.musicboard;

import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

import javax.annotation.Resource;

import jukebox.model.common.CommentVO;
import jukebox.model.common.PagingBean;
import jukebox.model.musiccomment.MusicCommentDAO;

import org.springframework.stereotype.Service;

@Service
public class MusicBoardServiceImpl implements MusicBoardService {
	@Resource(name="musicBoardDAOImpl")
	private MusicBoardDAO musicboardDAO;
	@Resource(name="musicCommentDAOImpl")
	private MusicCommentDAO musiccommentDAO;
	
	/**
	 * @method : writeContent
	 * @author : 김준섭
	 * @since : 2014-06-24
	 * @param : MusicBoardVO mbvo - 등록될 음악게시물 정보
	 * @return : void
	 * @comment : 음악게시물을 등록하기 위한 함수 
	 */
	@Override
	public void writeContent(MusicBoardVO mbvo) {
		musicboardDAO.writeContent(mbvo);
	}

	/**
	 * @method : updateContent
	 * @author : 김준섭
	 * @since : 2014-06-25
	 * @param : MusicBoardVO mbvo - 수정될 음악게시물 정보
	 * @return : void
	 * @comment : 음악게시물을 수정하기 위한 함수 
	 */
	@Override
	public void updateContent(MusicBoardVO mbvo) {
		musicboardDAO.updateContent(mbvo);
	}

	/**
	 * @method : deleteContent
	 * @author : 김준섭
	 * @since : 2014-06-25
	 * @param : int no - 삭제될 음악게시물 번호
	 * @return : void
	 * @comment : 음악게시물을 삭제하기 위한 함수 
	 */
	@Override
	public void deleteContent(int no) {
		musicboardDAO.deleteContent(no);
	}

	/**
	 * @method : pagingContent
	 * @author : 김준섭
	 * @since : 2014-06-23
	 * @param : MusicBoardVO mbvo - 검색 정보를 담은 객체
	 * @return : Map - 페이지의 정보를 담은 Map
	 * 						페이지 정보를 담은 pagingBean
	 * 						검색 정보를 담은 mbvo
	 * 						한 페이지의 게시물 리스트를 담은 list
	 * @comment : 검색된 한 페이지에 해당하는 게시물 리스트를 받아오기 위한 함수 
	 */
	@Override
	public Map pagingContent(MusicBoardVO mbvo) {
		PagingBean pagingBean = new PagingBean(musicboardDAO.getTotalContent(mbvo), 1);
		Map map = new HashMap<>();
		map.put("pagingBean", pagingBean);
		map.put("mbvo", mbvo);
		List list = musicboardDAO.getContentListPerPage(map);
		map.put("list", list);
		return map;
	}
	
	/**
	 * @method : pagingMoreContent
	 * @author : 김준섭
	 * @since : 2014-06-23
	 * @param : MusicBoardVO mbvo - 검색 정보를 담은 객체
	 * 				int nowPage - 현재 페이지 번호
	 * @return : Map - 페이지의 정보를 담은 Map
	 * 						페이지 정보를 담은 pagingBean
	 * 						검색 정보를 담은 mbvo
	 * 						한 페이지의 게시물 리스트를 담은 list
	 * @comment : 검색된 추가 페이지에 해당하는 게시물 리스트를 받아오기 위한 함수 
	 */
	@Override
	public Map pagingMoreContent(MusicBoardVO mbvo, int nowPage) {
		PagingBean pagingBean = new PagingBean(musicboardDAO.getTotalContent(mbvo), nowPage);
		Map map = new HashMap<>();
		map.put("pagingBean", pagingBean);
		map.put("mbvo", mbvo);
		List list = musicboardDAO.getContentListPerMorePage(map);
		map.put("list", list);
		return map;
	}

	/**
	 * @method : findContentByNo
	 * @author : 김준섭
	 * @since : 2014-06-24
	 * @param : int no - 검색할 게시물 번호
	 * @return : MusicBoardVO - 검색된 게시물의 상세정보
	 * @comment : 게시물의 상세정보를 게시물번호로 검색하는 함수
	 */
	@Override
	public MusicBoardVO findContentByNo(int no) {
		return musicboardDAO.findContentByNo(no);
	}

	/**
	 * @method : updateLike
	 * @author : 김준섭
	 * @since : 2014-06-27
	 * @param : int boardNo - 추천수를 증가시켜줄 게시물번호
	 * @return : Map - 추천수 증가후 결과정보를 담은 Map
	 * 						결과 메시지를 담은 msg
	 * 						증가된 추천수 갯수를 담은 likeCnt
	 * @comment : 음악게시물 추천수를 증가시키는 함수
	 */
	@Override
	public int updateLike(int boardNo) {
		return musicboardDAO.updateLike(boardNo);
	}

	/**
	 * @method : updateHit
	 * @author : 김준섭
	 * @since : 2014-06-27
	 * @param : int boardNo - 조회수를 증가시켜줄 게시물번호
	 * @return : void 
	 * @comment : 음악게시물 조회수를 증가시키는 함수
	 */
	@Override
	public void updateHit(int boardNo) {
		musicboardDAO.updateHit(boardNo);
	}

	/**
	 * @method : strCut
	 * @author : 김준섭
	 * @since : 2014-06-27
	 * @param : 	String szText - 문자열을 자를 원본 문자열
	 * 				String szKey - 문자열 자를 기준이 될 문자열
	 * 				int nLength - 자를 바이트 길이
	 * 				int nPrev - 이전포함 길이
	 * 				boolean isNotag - 태그문자를 제거할것인가
	 * 				boolean isAdddot - "..."을 뒤에 붙일것인가
	 * @return : String - 결과 문자열 
	 * @comment : 문자열을 자르기 위한 함수
	 */
	public String strCut(String szText, String szKey, int nLength, int nPrev,
			boolean isNotag, boolean isAdddot) { // 문자열 자르기

		String r_val = szText;
		int oF = 0, oL = 0, rF = 0, rL = 0;
		int nLengthPrev = 0;
		Pattern p = Pattern
				.compile("<(/?)([^<>]*)?>", Pattern.CASE_INSENSITIVE); // 태그제거
																		// 패턴

		if (isNotag) {
			r_val = p.matcher(r_val).replaceAll("");
		} // 태그 제거
		r_val = r_val.replaceAll("&amp;", "&");
		r_val = r_val.replaceAll("(!/|\r|\n|&nbsp;)", ""); // 공백제거

		try {
			byte[] bytes = r_val.getBytes("UTF-8"); // 바이트로 보관
			if (szKey != null && !szKey.equals("")) {
				nLengthPrev = (r_val.indexOf(szKey) == -1) ? 0 : r_val
						.indexOf(szKey); // 일단 위치찾고
				nLengthPrev = r_val.substring(0, nLengthPrev).getBytes("MS949").length; // 위치까지길이를
																						// byte로
																						// 다시
																						// 구한다
				nLengthPrev = (nLengthPrev - nPrev >= 0) ? nLengthPrev - nPrev
						: 0; // 좀 앞부분부터 가져오도록한다.
			}

			// x부터 y길이만큼 잘라낸다. 한글안깨지게.
			int j = 0;

			if (nLengthPrev > 0)
				while (j < bytes.length) {
					if ((bytes[j] & 0x80) != 0) {
						oF += 2;
						rF += 3;
						if (oF + 2 > nLengthPrev) {
							break;
						}
						j += 3;
					} else {
						if (oF + 1 > nLengthPrev) {
							break;
						}
						++oF;
						++rF;
						++j;
					}
				}

			j = rF;

			while (j < bytes.length) {
				if ((bytes[j] & 0x80) != 0) {
					if (oL + 2 > nLength) {
						break;
					}
					oL += 2;
					rL += 3;
					j += 3;
				} else {
					if (oL + 1 > nLength) {
						break;
					}
					++oL;
					++rL;
					++j;
				}
			}

			r_val = new String(bytes, rF, rL, "UTF-8"); // charset 옵션

			if (isAdddot && rF + rL + 3 <= bytes.length) {
				r_val += "...";
			} // ...을 붙일지말지 옵션
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}

		return r_val;
	}

	/**
	 * @method : getRankListByLike
	 * @author : 김준섭
	 * @since : 2014-06-27
	 * @return : List<MusicBoardVO> - 1~10위의 음악정보
	 * @comment : 음악을 추천수 기준으로 1~10위를 검색하는 함수 
	 */
	@Override
	public List<MusicBoardVO> getRankListByLike() {
		int cutByte = 10;
		List<MusicBoardVO> list = musicboardDAO.getRankListByLike();
		for(MusicBoardVO mbvo:list){
			String title = mbvo.getTitle();
			mbvo.setTitle(strCut(title, null, 10, 0, true, true));
		}
		System.out.println(list.size());
		return list;
	}

	/**
	 * @method : pagingComment
	 * @author : 김준섭
	 * @since : 2014-06-23
	 * @param : int boardNo - 댓글을 검색할 게시물 번호
	 * 				int nowPage - 댓글의 페이징 번호
	 * @return : Object - 페이지의 정보를 담은 Map
	 * 						페이지 정보를 담은 pagingBean
	 * 						게시물 번호를 담은 boardNo
	 * 						한 페이지의 댓글 리스트를 담은 list
	 * @comment : 검색된 한 페이지에 해당하는 댓글 리스트를 받아오기 위한 함수 
	 */
	@Override
	public Object pagingComment(int boardNo, int nowPage) {
		PagingBean pagingBean = new PagingBean(musiccommentDAO.getAllCommentCount(boardNo), nowPage);
		Map map = new HashMap<>();
		map.put("pagingBean", pagingBean);
		map.put("boardNo", boardNo);
		List list = musiccommentDAO.findCommentListPerPage(map);
		map.put("list", list);
		return map;
	}
	
	/**
	 * @method : writeComment
	 * @author : 김준섭
	 * @since : 2014-06-26
	 * @param : CommentVO mcvo - 등록할 음악 댓글의 정보
	 * 				int boardNo - 댓글이 등록될 게시물 번호
	 * @return : void
	 * @comment : 음악게시물의 댓글 추가하기 위한 함수 
	 */
	@Override
	public void writeComment(CommentVO mcvo) {
		musiccommentDAO.writeComment(mcvo);
	}

	/**
	 * @method : updateComment
	 * @author : 김준섭
	 * @since : 2014-06-26
	 * @param : CommentVO mcvo - 수정될 음악 댓글 정보
	 * @return : void
	 * @comment : 음악 댓글을 수정하기 위한 함수 
	 */
	@Override
	public void updateComment(CommentVO mcvo) {
		musiccommentDAO.updateComment(mcvo);
	}

	/**
	 * @method : deleteCommentbyNo
	 * @author : 김준섭
	 * @since : 2014-06-26
	 * @param : int no - 삭제될 음악 댓글 번호
	 * @return : void
	 * @comment : 음악 댓글을 삭제하기 위한 함수 
	 */
	@Override
	public void deleteComment(int no) {
		musiccommentDAO.deleteCommentbyNo(no);
	}

	/**
	 * @method : findCommentListByBoardNo
	 * @author : 김준섭
	 * @since : 2014-06-26
	 * @param : int no - 게시물 번호
	 * @return : List<CommentVO> - 게시물의 전체 댓글 정보
	 * @comment : 게시물에 해당하는 전체 댓글을 검색하기 위한 함수
	 */
	@Override
	public List<CommentVO> findCommentListByBoardNo(int no) {
		return musiccommentDAO.findCommentListByBoardNo(no);
	}
	
	/**
	 * @method : findCommentByCommentNo
	 * @author : 김준섭
	 * @since : 2014-06-26
	 * @param : int no - 검색할 댓글 번호
	 * @return : CommentVO - 댓글 정보
	 * @comment : 댓글 번호를 검색하여 댓글 정보를 가져오기 위한 함수
	 */
	@Override
	public CommentVO findCommentByCommentNo(int no) {
		return musiccommentDAO.findCommentByCommentNo(no);
	}

}
